import { message } from 'antd';
import { Editor, Range, Transforms, Path, Point, Node, Descendant } from 'slate';
import { DocItem, DocItemType, SlateDescendant, SlateEditorInputInfo } from './../../slate-editor/types';

import { checkDocItemIsTitleParagraph, getSlateEditorInputInfoByInputData, sortTextStyleMapAndFindMaxIndex, updateDocItemPlainText } from './editor-doc-item-generate';
import { isHeading } from '../../slate-editor/utils';
import { SpeciesInfoType } from '../../../utils/types';
import emitter from '../../../utils/emitter';

/**
 * 获取数据项类型
 * @param children
 * @param index
 * @returns
 */
const getItemType = (children: SlateDescendant[], index: number) => {
  const item = children[index];
  return !item || 'text' in item ? null : item.type || null;
};
/**
 * 获取路径字符串
 * @param point
 * @returns
 */
const getPathString = (point: Point) => point.path.join('') + `@${point.offset}`;

/**
 * 获取将要删除掉的文本字段
 * @param editor 
 * @param selectionPosition 
 * @returns 
 */
const getDeletionText = (editor, selectionPosition) => {
  if (!selectionPosition) {
    return '';
  }
  const [start, end] = selectionPosition;
  const range = { anchor: start, focus: end };
  const text = Editor.string(editor, range);
  return text;
};

/**
 * 本次删除受影响的节点
 * @param editor 
 * @param selectionPosition 
 * @returns 
 */
const findAffectedNodes = (editor: Editor, selectionPosition: [Point, Point]) => {
  const affectedNodes = [];
  if (!selectionPosition) {
    return affectedNodes;
  }
  const [start, end] = selectionPosition;
  const range = { anchor: start, focus: end };

  //@ts-ignore
  for (const [node, path] of Node.nodes(editor)) {
    if (path.length > 0 && Range.includes(range, path)) {
      affectedNodes.push({ node, path });
    }
  }

  return affectedNodes;
};

/**
 * 
 * @param editor 
 * @param children 
 */
const getEditorChildrenTargetElementText = (children: Descendant[], childIndex: number): string => {
  let elementText = '';
  if (children[childIndex]) {
    //@ts-ignore
    children[childIndex].children.forEach(ele => {
      if (ele.text) {
        elementText += ele.text;
      } else if (ele.type == 'input') {
        elementText += ele.initialVal;
      }
    })
  }
  return elementText;
}

/**
 * 禁止清除检查
 * @param children
 * @param selectionPosition
 * @returns
 */
export const checkDisableClearV2 = (editor: Editor, selectionPosition: [Point, Point] | null) => {
  const { children } = editor;
  const deletetionText = getDeletionText(editor, selectionPosition);
  const affectedNodeRecords = findAffectedNodes(editor, selectionPosition);
  let paragraphInfoList: { type: DocItemType, id: string }[] = [];  //记录涉及到的段落信息
  let deviceInputInfoList: SlateEditorInputInfo[] = [];
  let isIncludeTitleNode = false;   //是否包含标题栏（如果包含标题栏，暂时不允许与其他段落一起操作）
  affectedNodeRecords.forEach(nodeRecord => {
    if (nodeRecord.node && nodeRecord.node.children && nodeRecord.node.children.length) {
      let findIndex = -1;
      paragraphInfoList.forEach((item, index) => {
        if (item.id == nodeRecord.node.id) {
          findIndex = index;
        }
      })
      if (findIndex == -1) {
        paragraphInfoList.push({
          id: nodeRecord.node.id,
          type: nodeRecord.node.type,
        })
      }
      if (checkDocItemIsTitleParagraph(nodeRecord.node.type)) {
        isIncludeTitleNode = true;
      }
      if (nodeRecord.node.type == 'input' && nodeRecord.node.mark) {
        let inputData = {};
        inputData[`${nodeRecord.node.id}/${nodeRecord.node.mark}`] = nodeRecord.node.initialVal;
        const inputInfo = getSlateEditorInputInfoByInputData(inputData);
        deviceInputInfoList.push(inputInfo);
      }
    }
  })
  if (!selectionPosition) {
    return false;
  }
  const [startPoint, endPoint] = selectionPosition;
  let flag = false;
  let msg = '禁止操作，该操作会导致非法合并';
  const startItemType = getItemType(children, startPoint.path[0]);
  const isStartHeading = isHeading(startItemType as DocItemType);
  if (
    isIncludeTitleNode &&
    paragraphInfoList.length > 1
  ) {
    msg = '标题段落不能与其它段落同时删除';
    flag = true;
  } else if (
    deviceInputInfoList.length &&
    deviceInputInfoList.filter(ele => {
      return ele.realInputMarker.includes('$[S') || ele.realInputMarker.includes('$[X');
    }).length > 1
  ) {
    msg = '请勿同时删除多个设备节点(当前删除内容包含两个或两个以上的项目节点)';
    flag = true;
  } else {
    if (getPathString(startPoint) === getPathString(endPoint)) {
      flag =
        startPoint.offset === 0 &&
        startPoint.path.slice(1).every((i) => i === 0) &&
        startItemType !== getItemType(children, startPoint.path[0] - 1);
      if (!flag) {
        flag = !!startItemType && isStartHeading && startPoint.path[1] <= 2 && !startPoint.offset;
        msg = '禁止操作，标题序号不可直接删除';
      }
    } else {
      // flag =
      //   !Array(endPoint.path[0] - startPoint.path[0])
      //     .fill(null)
      //     .every((_, index) => getItemType(children, startPoint.path[0] + index) === DocItemType.CP) &&
      //   !Array(endPoint.path[0] - startPoint.path[0])
      //     .fill(null)
      //     .every((_, index) => getItemType(children, startPoint.path[0] + index) === DocItemType.P);
      // if (!flag && isStartHeading) {
      //   flag = startPoint.path[1] <= 2;
      //   msg = '禁止操作，标题序号不可删除2';
      // }
    }
    //系统提示，用户可自主选择
    if (deviceInputInfoList.length &&
      deviceInputInfoList.filter(ele => {
        return ele.realInputMarker.includes('$[S') || ele.realInputMarker.includes('$[X');
      }).length == 1) {
      const isConfirmed = window.confirm('确定删除所选文本内容?此操作会一并删除投资估算表中项目');
      if (isConfirmed) {
        flag = false;
      } else {
        flag = true;
      }
    } else if (
      isIncludeTitleNode &&
      paragraphInfoList.length == 1 &&
      endPoint.offset - startPoint.offset === getEditorChildrenTargetElementText(children, endPoint.path[0]).length
    ) {
      const isConfirmed = window.confirm('确定删除所选标题？删除后该标题下内容将全部合并至上一级标题');
      if (isConfirmed) {
        flag = false;
      } else {
        flag = true;
      }
    }
  }
  if(flag && msg == "禁止操作，该操作会导致非法合并"){
    // console.log("ddd->", affectedNodeRecords);
    const titleDocItemNode = affectedNodeRecords.find(node => node.node && node.node.id.includes('-usp'));
    if(titleDocItemNode){
      emitter.emit('RemoveLine', { docItemId: titleDocItemNode['node'].id })
    }
  }else {
    flag && msg && message.warning(msg);
  }
  return flag;
};

/**
 * 禁止换行检查
 * @param children
 * @param selectionPosition
 * @returns
 */
export const checkDisableNewline = (editor: Editor, selectionPosition: [Point, Point] | null) => {
  const {
    children
  } = editor;
  if (!selectionPosition) return false;
  const [startPoint, endPoint] = selectionPosition;
  const affectedNodeRecords = findAffectedNodes(editor, selectionPosition);
  console.log("affectedNodeRecords---->", affectedNodeRecords);
  let flag = false;
  const msg = '禁止操作，标题不允许换行操作';
  if (getPathString(startPoint) === getPathString(endPoint)) {
    const _isHeading = isHeading(getItemType(children, startPoint.path[0]) as DocItemType);
    if (_isHeading) {
      flag = _isHeading;
      if (isCursorAtEndOfBlock(editor)) {
        const titleDocItemNode = affectedNodeRecords.find(node => {
          return node['node'].type && node['node'].id && node['node'].type.includes('h')
        })
        if (titleDocItemNode) {
          console.log("titleDocItemNode--->", titleDocItemNode)
          emitter.emit('AddNewLine', { docItemId: titleDocItemNode['node'].id })
        }
      } else {
        flag && message.warning(msg);
      }
    }
  }
  return flag;
};

export const moveToParagraphById = (editor: Editor, paragraphId: string, toStart = true) => {
  try {
    // console.log("遍历文档树以找到具有指定ID的节点及其路径")
    // 遍历文档树以找到具有指定ID的节点及其路径
    //@ts-ignore
    for (const [node, path] of Node.nodes(editor, { at: [] })) {
      if (node.id === paragraphId) {
        // 根据toStart的值，移动光标到段落的开始或末尾
        const newPoint = toStart ? Editor.start(editor, path) : Editor.end(editor, path);
        Transforms.select(editor, newPoint);
        break;
      }
    }
  } catch (e) {

  }
};

export const getSlateItem = (children: SlateDescendant[], path: Path | null) =>
  path?.slice(1)?.reduce((r, c) => ('text' in r ? r : r?.children?.[c]), children[path[0]]);

const isCursorAtEndOfBlock = (editor: Editor) => {
  // 首先，确保有一个当前的选择范围
  if (!editor.selection) return false;

  // 获取选择范围的结束点，即光标位置
  const { focus } = editor.selection;

  // 获取光标所在的节点和路径
  const [node, path] = Editor.node(editor, focus.path);

  // 如果节点是文本节点，我们检查它是否是其父级的最后一个节点
  //@ts-ignore
  if (Editor.isBlock(editor, node)) {
    const parent = Editor.parent(editor, path);
    const [parentNode, parentPath] = parent;

    // 获取父节点的最后一个子节点
    const lastChild = parentNode.children[parentNode.children.length - 1];

    // 检查当前节点是否是父节点的最后一个子节点
    if (node === lastChild) {
      // 检查光标是否位于节点的末尾
      const endOfNode = Editor.end(editor, path);
      return Point.equals(focus, endOfNode);
    }
  }

  return false;
};


export const checkDisableEditor = (editor: Editor, selectionPosition: [Point, Point] | null): boolean => {
  let flag = false;
  let msg = '';
  let isIncludeTitleNode = false;
  const affectedNodeRecords = findAffectedNodes(editor, selectionPosition);
  console.log("affectedNodeRecords--->", affectedNodeRecords);
  affectedNodeRecords.forEach(nodeRecord => {
    if (checkDocItemIsTitleParagraph(nodeRecord.node.type)) {
      isIncludeTitleNode = true;
    }
  })
  if (isIncludeTitleNode) {
    if (isCursorAtEndOfBlock(editor)) {
      console.log("末尾--->")
    } else {
      console.log("非末尾--->")
      msg = '请在大纲菜单栏修改';
      flag = true;
    }
  }
  if (
    affectedNodeRecords &&
    affectedNodeRecords.filter(nodeRecord => nodeRecord.node.id && nodeRecord.node.id?.includes('-SP-')).length &&
    !localStorage.getItem('confirmedToChangeSystemParagraph')
  ) {
    const isConfirmedToChangeSystemParagraph = window.confirm('请确保规划项目已确定，再次修改规划项目后，系统会删除您所做的修改');
    if (isConfirmedToChangeSystemParagraph) {
      flag = false;
      localStorage.setItem('confirmedToChangeSystemParagraph', "true");
    } else {
      flag = true;
    }
  }
  flag && msg && message.warning(msg)
  return flag;
}

export const fillSpeciesNameInfoForSlateEditor = (docItemList: DocItem[], speciesInfoList: SpeciesInfoType[]) => {
  let speciesAppearance = {};
  let genusAppearance = {};
  let textStyleMapIndex = 5000;
  const speciesOrderMap = new Map();
  speciesInfoList.forEach((item, index) => {
    let docItemIndex = -1;
    let docItemTextIndexOf = -1;
    const findIndex = docItemList.findIndex(docItem => docItem.plainText && docItem.plainText.indexOf(item.species_c) !== -1);
    if (findIndex != -1) {
      docItemIndex = findIndex;
      docItemTextIndexOf = docItemList[findIndex].plainText.indexOf(item.species_c);
    }
    speciesOrderMap.set(item.species_c, { info: item, docItemIndex, docItemTextIndexOf })
  });
  const speciesOrderList = Array.from(speciesOrderMap.values());
  speciesOrderList.sort((a, b) => {
    if (a.docItemIndex !== b.docItemIndex) {
      return a.docItemIndex - b.docItemIndex;
    } else {
      return a.docItemTextIndexOf - b.docItemTextIndexOf;
    }
  });
  const speciesInfoListSorted = speciesOrderList.map(ele => ele.info);
  docItemList.forEach(docItem => {
    if (!docItem.textStyleMap) {
      docItem.textStyleMap = {};
    }
    let needToUpdatePlainText = false;
    speciesInfoListSorted.forEach(({ genus, canorical_me, species_c }) => {
      let regex = new RegExp(`${species_c}(\\s*\\(.*?\\))?(?!\\s*\\()`, "g");
      let match = null;
      while ((match = regex.exec(docItem.text)) !== null) {
        // 如果物种已经被处理过，跳过
        if (speciesAppearance[species_c]) continue;
        const isGenusFirstAppearance = genusAppearance[genus] === undefined;
        genusAppearance[genus] = false;
        speciesAppearance[species_c] = true;

        const placeholder = `$$[${textStyleMapIndex}]`;
        let latinName = isGenusFirstAppearance ? canorical_me : `${genus[0]}. ${canorical_me.split(" ")[1]}`;
        if (isGenusFirstAppearance) {
          let replacementText = `${species_c} (${placeholder})`;
          docItem.text = docItem.text.substring(0, match.index) + replacementText + docItem.text.substring(match.index + match[0].length);
          docItem.textStyleMap[placeholder] = {
            text: latinName,
            italic: isGenusFirstAppearance, // 首次出现使用斜体
          };
        } else {
          let latinNameBefore = `${genus[0]}. `;
          let latinNameAfter = `${canorical_me.split(" ")[1]}`
          textStyleMapIndex++; // 索引递增
          const afterPlaceholder = `$$[${textStyleMapIndex}]`;
          docItem.textStyleMap[placeholder] = {
            text: latinNameBefore,
            italic: isGenusFirstAppearance
          };
          docItem.textStyleMap[afterPlaceholder] = {
            text: latinNameAfter,
            italic: true,
          };
          let replacementText = `${species_c} (${placeholder}${afterPlaceholder})`;
          docItem.text = docItem.text.substring(0, match.index) + replacementText + docItem.text.substring(match.index + match[0].length);
        }
        needToUpdatePlainText = true;
        textStyleMapIndex++;
      }
    });
    if (needToUpdatePlainText) {
      docItem = updateDocItemPlainText(docItem)
    }
  });
  return docItemList;
};

/**
 * 禁止清除检查
 * @param children
 * @param selectionPosition
 * @param allowStartPosition
 * @returns
 */
export const checkDisableClear = (
  children: SlateDescendant[],
  selectionPosition: [Point, Point] | null,
  allowStartPosition = false,
) => {
  if (!selectionPosition) return false;
  if (isFirstBlock(selectionPosition)) return false;
  const [startPoint, endPoint] = selectionPosition;
  let flag = false;
  let msg = '禁止操作，该操作会导致非法合并';
  const startItemType = getItemType(children, startPoint.path[0]);
  const isStartHeading = isHeading(startItemType as DocItemType);
  if (getPathString(startPoint) === getPathString(endPoint)) {
    flag =
      startPoint.offset === 0 &&
      startPoint.path.slice(1).every((i) => i === 0) &&
      startItemType !== getItemType(children, startPoint.path[0] - 1);
    if (!flag) {
      flag = !!startItemType && isStartHeading && startPoint.path[1] <= 2 && !startPoint.offset;
      msg = '禁止操作，标题序号不可删除';
    } else if (allowStartPosition) flag = false;
  } else {
    let length = endPoint.path[0] - startPoint.path[0] + 1;
    if (endPoint.path.slice(1).every((item) => !item) && !endPoint.offset) length -= 1;
    if (length > 1)
      flag = !Array(length)
        .fill(null)
        .every((_, index) => {
          const type = getItemType(children, startPoint.path[0] + index);
          return [DocItemType.CP, DocItemType.P].includes(type as DocItemType);
        });
    else if (!flag && isStartHeading) {
      flag = startPoint.path[1] <= 1;
      msg = '禁止操作，标题序号不可删除';
    }
  }
  flag && message.warning(msg);
  return flag;
};

const isFirstBlock = ([startPoint, endPoint]: [Point, Point]) => {
  const {
    path: [startIndex],
  } = startPoint;
  const {
    path: [endIndex],
  } = endPoint;
  return (
    (startIndex === endIndex && startIndex === 0) || (endPoint.path.slice(1).every((item) => !item) && !endPoint.offset)
  );
};

/**
 * 禁止输入
 * @param children
 * @param selectionPosition
 * @param silence
 * @returns
 */
export const checkDisableInput = (
  children: SlateDescendant[],
  selectionPosition: [Point, Point] | null,
  silence = false,
) => {
  if (!selectionPosition) return false;
  if (isFirstBlock(selectionPosition)) return false;
  const [startPoint, endPoint] = selectionPosition;
  const startItemType = getItemType(children, startPoint.path[0]);
  const isStartHeading = isHeading(startItemType as DocItemType);
  let flag = false;
  let msg = '';
  if (getPathString(startPoint) === getPathString(endPoint)) {
    flag = isStartHeading && startPoint.path.slice(1).every((item) => !item);
    msg = '禁止操作，标题的开始位置不能进行输入操作';
  } else {
    let length = endPoint.path[0] - startPoint.path[0] + 1;
    if (endPoint.path.slice(1).every((item) => !item) && !endPoint.offset) length -= 1;
    if (length > 1) {
      flag = !Array(length)
        .fill(null)
        .every((_, index) => {
          const type = getItemType(children, startPoint.path[0] + index);
          return [DocItemType.CP, DocItemType.P].includes(type as DocItemType);
        });
      msg = '禁止操作，该操作会导致非法合并';
    }
    if (!flag && isStartHeading) {
      flag = startPoint.path.slice(1).every((item) => !item);
      msg = '禁止操作，标题序号不可删除';
    }
  }
  !silence && flag && message.warning(msg);
  return flag;
};
